#include "ZY_Flash.h"
#include "malloc.h"

#define FLASH_WAITETIME	50000
#define USER_Flash_ADDR  0x0800F800

extern Mallco_dev mallco_dev; //内存管理器
/// @brief 擦除flash
/// @param  
/// @return 
HAL_StatusTypeDef FLASH_Erase(int page,int page_num)
{
	uint32_t PageError = 0;
	FLASH_EraseInitTypeDef EraseInitStruct;
	HAL_FLASH_Unlock();
	EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
 	EraseInitStruct.Page = page;
 	EraseInitStruct.NbPages     = page_num;	
 	if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
 	{
 		return HAL_ERROR;	 
 	}
 	FLASH_WaitForLastOperation(FLASH_WAITETIME);
 	
  HAL_FLASH_Lock();
 
 	return HAL_OK;
}

/// @brief 向flash写入数据 （8字节对齐）
/// @param Address flash 地址
/// @param pBuffer 数据
/// @param Num 数据长度
void FLASH_Write(uint32_t Address, uint8_t* pBuffer, uint8_t Num)   
{                                                  
  uint32_t data1=0;
	uint32_t data2=0;
	uint64_t data_write=0;
	HAL_FLASH_Unlock();	
	 for(uint8_t i=0;i<Num/8;i++)
	 {
		 data1=pBuffer[0+i*8]|(pBuffer[1+i*8]<<8)|(pBuffer[2+i*8]<<16)|(pBuffer[3+i*8]<<24);
		 data2=pBuffer[4+i*8]|(pBuffer[5+i*8]<<8)|(pBuffer[6+i*8]<<16)|(pBuffer[7+i*8]<<24);
		 data_write=(data2);
     data_write=(data_write<<32)|data1; 
     HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address,data_write);		
     Address +=8;		 
	 }
	 HAL_FLASH_Lock();
}
/// @brief 从flash 中读取一个uint32_t
/// @param faddr flash 地址
/// @return 
uint32_t FLASH_ReadWord(uint32_t faddr)
{
	return *(uint32_t*)faddr; 
}
/// @brief 从flash 指定位置读取数据(4字节对齐)
/// @param Address 地址
/// @param pBuffer 数据缓存
/// @param size 长度
void FLASH_Read(uint32_t Address,uint8_t *pBuffer,uint8_t size)
{
	uint32_t data=0;
	for(uint8_t i=0;i<size/4;i++)
	{
		data=FLASH_ReadWord(Address);
		pBuffer[0+i*4]=data;
		pBuffer[1+i*4]=data>>8;
		pBuffer[2+i*4]=data>>16;
		pBuffer[3+i*4]=data>>24;
		Address+=4;
	}
}

//用户flash 擦除
uint8_t user_flash_erase(void)
{
	if(FLASH_Erase(31,1)==HAL_OK)
	{
		return 0;
	}
	return 1;
}
//用户Flash 保存数据
void user_flash_write(uint16_t writeAddr,uint8_t *buffer,uint16_t len)
{
	uint8_t *buf;
	uint16_t write_len=0;
	if(len%8!=0)
	{
		write_len=(8-len%8)+len;
	}
	buf = (uint8_t *)mymalloc(&mallco_dev, len);
	if(buf)
	{
		mymemcpy(buf,buffer,len);
		FLASH_Write(USER_Flash_ADDR+writeAddr,buf,write_len);
		myfree(&mallco_dev,buf);
	}
}

void user_flash_read(uint16_t readAddr,uint8_t *buffer,uint16_t len)
{
	uint8_t *buf;
	uint32_t data=0;
	uint32_t read_len=0;
	if(len%4!=0)
	{
		read_len=(4-len%4)+len;
	}
	buf=(uint8_t *)mymalloc(&mallco_dev,read_len);
	if(buf)
	{
		FLASH_Read(USER_Flash_ADDR+readAddr,buf,read_len);
		mymemcpy(buffer,buf,len);
		myfree(&mallco_dev,buf);
	}
}